package at.com.vn.chess.applet;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.table.DefaultTableModel;

import vn.com.bip.office.smart.util.XMLHelper;
import vn.nnn.shogi.quanco.QuanCo;
import at.com.vn.chess.entity.ChatUser;
import at.com.vn.chess.entity.ChessRow;
import at.com.vn.chess.entity.RoomTable;
import at.com.vn.chess.listener.ChessTableListener;
import at.com.vn.chess.listener.DialogClickListener;
import at.com.vn.chess.network.ClientUtil;
import at.com.vn.chess.util.ChessTable;
import at.com.vn.chess.util.Const;
import at.com.vn.chess.util.Msg;
import at.com.vn.chess.util.MultiColumn;

public class ChatApplet extends JApplet implements ActionListener, Runnable {

	private static final long serialVersionUID = -6869438049346937247L;

	String url_servlet_base = Const.URL_CHESS_APPLICATION;
	String url_servlet_chat_public = url_servlet_base + "/chatPublic.htm";
	String url_servlet_chat_private = url_servlet_base + "/chatPrivate.htm";

	// Variable
	private ArrayList<ChatUser> lstReturnUser;
	private ArrayList<ChessRow> lstReturnChessTable = new ArrayList<ChessRow>();

	private ClientUtil clientUtil;

	// Basic Components
	private JPanel panel = new JPanel();
	private ChessTable chessTable = new ChessTable();
	private ChessFrame chessFrame = null;
	private TextArea textResult = new TextArea();

	MultiColumn listUser;

	private JLabel lblTitle = new JLabel(Const.SHOGI_TABLE_TITLE);
	private TextField textfield = new TextField();
	private JButton button = new JButton();
	private Font ver = new Font(Const.FONT_PUBLIC_CHAT, Font.CENTER_BASELINE,
			12);

	private JComboBox feelings = new JComboBox(Const.FEELING);
	private JButton sendfeel = new JButton();

	// All Strings
	private String name = "Mr X";
	private String currentRoomID;
	private String feels;

	// Threads
	private Thread thread;

	// Thread t1 = new Thread(this);
	// Messages msg;
	// Thread t2 = new Thread(msg);
	private int tableID = 0;

	protected boolean linkClicked = false;

//	private String url_servlet = Const.URL_CHESS_APPLICATION;

	public void init() {

		System.out.println("Khoi dong mot bang chat");

		// Get parameter from web
		name = this.getParameter(Const.WEB_PARAM_USER_ID);
		currentRoomID = this.getParameter(Const.WEB_PARAM_ROOM_ID);
		url_servlet_base = this.getParameter(Const.WEB_PARAM_SERVER_URL_BASE);
		url_servlet_chat_public = url_servlet_base + "/chatPublic.htm";
		url_servlet_chat_private = url_servlet_base + "/chatPrivate.htm";

		if (url_servlet_base == null || url_servlet_base.equals("")) {
			url_servlet_base = Const.URL_CHESS_APPLICATION;
			url_servlet_chat_public = url_servlet_base + "/chatPublic.htm";
			url_servlet_chat_private = url_servlet_base + "/chatPrivate.htm";
		}

		System.out.println("url: " + Const.URL_CHESS_APPLICATION);

		if ((name == null) || name.equals("")) {
//			Random gen = new Random();
//			name = "User" + gen.nextInt(100);
			name = "nhai";
		}

		System.out.println("Qua buoc 1");

		if ((currentRoomID == null) || currentRoomID.equals("")) {
//			Random gen = new Random();
//			currentRoomID = "room" + gen.nextInt(100);
			currentRoomID = "1";
		}

		clientUtil = new ClientUtil(getCodeBase(), url_servlet_chat_public, name,
				currentRoomID);

		setSize(795, 500);

		JScrollPane container = new JScrollPane(chessTable);
		getContentPane().add(container, java.awt.BorderLayout.WEST);
		chessTable.setLayout(null);

		// The first applet load, set 1 row for chess table
//		lstReturnChessTable.add(new ChessRow(1, currentRoomID, Const.PLAYER_NAME_BLANK,
//				Const.PLAYER_NAME_BLANK, 0, 0));
//		chessTable.setDataLink(lstReturnChessTable);

		chessTable.setOnClickListener(new DialogClickListener() {
			@Override
			public void createRowClicked() {
				// Check available blank chess table on this room
//				System.out.println("ChatApplet: Tao moi mot room");
//				if (isAvaiBlankChessTable()) {
//					JOptionPane.showMessageDialog(getParent(),
//							"Please use available blank chess table");
//				} else {
//					// Add new row
//					System.out.println("ChatApplet: Mot room moi da duoc tao ");
//					String xmlMsg = prepareDoChessTableMsg(
//							Const.PROCESS_DO_CHESS_TABLE_ADD_CHESS_TABLE,
//							" has created new chess table...");
//					clientUtil.sendBroadcastMessage(xmlMsg);
//				}
				JOptionPane.showMessageDialog(getParent(),
						"Please use available blank chess table");
			}

			@Override
			public void linkClicked(int rowClicked, int columnClicked) {
				// Only one click on link, when browser is not
				// IE(firefox and other)
				if (linkClicked) {
					return;
				}
				linkClicked = true;
				System.out.println("ChatApplet: user tham gia vao room");

				// get row clicked
				tableID = Integer.parseInt(String.valueOf(chessTable.getModel()
						.getValueAt(rowClicked, 0)));

//				ChessRow chessRowClicked = getChessRowByID(id);

				// chessRowClicked.setCurrentUserId(name);
				String title = new StringBuilder().append("Table ")
						.append(tableID).append(" -- ")
						.append(name).append("'s window").toString();

				// Send to server
//				String xmlMsg = XMLHelper.convertListObjectToXML(
//						chessRowClicked,
//						Const.PROCESS_DO_CHESS_TABLE_CLICK_LINK_CHESS_TABLE,
//						ChessRow.class);
//
//				clientUtil.sendBroadcastMessage(xmlMsg);

//				tableID = chessRowClicked.getTableId();

				chessFrame = new ChessFrame(title, url_servlet_chat_private,
						name, currentRoomID, tableID, ChatApplet.this);
				chessFrame.setListener(new ChessTableListener() {
					@Override
					public void refreshMainBoard() {

						// Only one click on link, when browser is not
						// IE(firefox and other)
						linkClicked = false;
						
						clientUtil.sendBroadcastMessage(XMLHelper.convertListObjectToXML(
								new RoomTable(Integer.parseInt(currentRoomID), tableID), 
								Const.PROCESS_DO_CHESS_TABLE_REFRESH, RoomTable.class));

//						String xmlMsg;
//						// When user left, set player name for chess table
//						ChessRow chessRow = getRowByPlayer(name);
//						if (chessRow != null) {
//							if (chessRow.getBlackOwner().equals(name)) {
//								chessRow.setBlackOwner(Const.PLAYER_NAME_BLANK);
//								chessRow.setBlackOwnerStatus(Const.NOT_JOINED);
//							}
//							if (chessRow.getWhiteOwner().equals(name)) {
//								chessRow.setWhiteOwner(Const.PLAYER_NAME_BLANK);
//								chessRow.setWhiteOwnerStatus(Const.NOT_JOINED);
//							}
//
//							xmlMsg = XMLHelper.convertListObjectToXML(chessRow,
//									Const.PROCESS_DO_CHESS_TABLE_LEFT,
//									ChessRow.class);
//							clientUtil.sendBroadcastMessage(xmlMsg);
//						}
					}

					@Override
					public void setPlayerClicked(String name, int playerColor,
							String status) {

						String xmlMsg;
						// When user left, set player name for chess table
						RoomTable table = new RoomTable(Integer.parseInt(currentRoomID), tableID);
						table.setStatus(status);
						if (playerColor == QuanCo.QUAN_DEN) {
							table.setPlayer1Id(name);
						} else if (playerColor == QuanCo.QUAN_TRANG) {
							table.setPlayer2Id(name);
						}
						
						xmlMsg = XMLHelper.convertListObjectToXML(table,
								Const.PROCESS_DO_CHESS_TABLE_JOIN,
								RoomTable.class);
						clientUtil.sendBroadcastMessage(xmlMsg);
					}
				});

				// open chesstable
				chessFrame.setMinimumSize(new Dimension(Const.DIALOG_WIDTH + 10,
						Const.DIALOG_HEIGHT + 32));
				chessFrame.setPreferredSize(new Dimension(Const.DIALOG_WIDTH + 10,
						Const.DIALOG_HEIGHT + 32));
				chessFrame.pack();
				chessFrame.setLocationRelativeTo(null);
				chessFrame.setVisible(true);
			}
		});

		getContentPane().add(lblTitle, java.awt.BorderLayout.PAGE_START);

		getContentPane().add(panel, java.awt.BorderLayout.CENTER);
		panel.setLayout(null);
		panel.setBackground(new Color(214, 237, 240));

		panel.add(textResult);
		textResult.setBounds(3, 20, 280, 350);
		textResult.setFont(ver);
		textResult.setEditable(false);
		textResult.setText("Tro chuyen vui ve\n");
		textResult.append("------------------------------------------\n");

		JLabel listTitle = new JLabel(
				"UserId       Win        Lost         Rank        Gold");
		panel.add(listTitle);
		listTitle.setBounds(285, 6, 250, 15);

		listUser = new MultiColumn(null, 5);

		panel.add(listUser);
		listUser.setBounds(286, 20, 270, 350);
		listUser.setFont(ver);
		listUser.setLayout(null);
		listUser.setSize(240, 350);

		panel.add(textfield);
		textfield.setBounds(3, 380, 280, 25);
		textfield.setFont(ver);
		textfield.setText("");
		textfield.requestFocus();
		textfield.addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				int key = e.getKeyCode();
				if (key == KeyEvent.VK_ENTER) {
//					Toolkit.getDefaultToolkit().beep();

					String xmlMsg = prepareChatMsg(
							Const.PROCESS_CHAT_PUBLIC_CHAT, textfield.getText());
					clientUtil.sendBroadcastMessage(xmlMsg);

					textfield.setText("");
				}
			}
		});

		panel.add(button);
		button.setBounds(3, 415, 280, 25);
		button.setText(name + " Says");
		button.setFont(ver);
		button.addActionListener(this);

		panel.add(feelings);
		feelings.setBounds(3, 450, 120, 25);
		feelings.setFont(ver);
		panel.add(sendfeel);

		sendfeel.setBounds(135, 450, 150, 25);
		sendfeel.setFont(ver);
		sendfeel.setText(Const.BUTTON_SEND_FEELING);
		sendfeel.addActionListener(this);

		String xmlMsg = prepareChatMsg(Const.PROCESS_CHAT_PUBLIC_JOIN,
				" has joined...");
		showResult(clientUtil.doPrivateData(xmlMsg));

		xmlMsg = prepareDoChessTableMsg(
				Const.PROCESS_DO_CHESS_TABLE_GET_CHESS_TABLE, " has joined...");
		showResult(clientUtil.doPrivateData(xmlMsg));

		xmlMsg = prepareChatMsg(Const.PROCESS_CHAT_PUBLIC_JOIN,
				" has joined...");
		clientUtil.sendBroadcastMessage(xmlMsg);

	}

	@Override
	public void start() {
		thread = new Thread(this);
		thread.start();
	}

	@Override
	public void destroy() {

		// Send to server
		String xmlMsg;
		// When user left, set player name for chess table
//		ChessRow chessRow = getRowByPlayer(name);
//		if (chessRow != null) {
//			if (chessRow.getBlackOwner().equals(name)) {
//				chessRow.setBlackOwner(Const.PLAYER_NAME_BLANK);
//				chessRow.setBlackOwnerStatus(1);
//			}
//			if (chessRow.getWhiteOwner().equals(name)) {
//				chessRow.setWhiteOwner(Const.PLAYER_NAME_BLANK);
//				chessRow.setWhiteOwnerStatus(1);
//			}
//
//			xmlMsg = XMLHelper.convertListObjectToXML(chessRow,
//					Const.PROCESS_DO_CHESS_TABLE_LEFT, ChessRow.class);
//			clientUtil.sendBroadcastMessage(xmlMsg);
//		}
		
		// When user left, remove out of list, show all client
		xmlMsg = prepareChatMsg(Const.PROCESS_CHAT_PUBLIC_LEFT, " has left...");
		clientUtil.sendBroadcastMessage(xmlMsg);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == button) {
			// sent to server
			String xmlMsg = prepareChatMsg(Const.PROCESS_CHAT_PUBLIC_CHAT,
					textfield.getText());
			clientUtil.sendBroadcastMessage(xmlMsg);
			textfield.setText("");
		}

		if (e.getSource() == sendfeel) {
			if (feelings.getSelectedItem().equals("I Feel ...")) {
				return;
			}

			feels = String.valueOf(feelings.getSelectedItem());
			String xmlMsg = prepareChatMsg(Const.PROCESS_CHAT_PUBLIC_CHAT,
					" feels " + feels);
			clientUtil.sendBroadcastMessage(xmlMsg);
		}

	}

	@Override
	public void run() {
		Thread thisThread = Thread.currentThread();
		while (thread == thisThread) {
			try {
				Thread.sleep(Const.ONE_SECOND);
			} catch (InterruptedException e) {
			}
			String xmlMsg = clientUtil.receiverMessage();
			showResult(xmlMsg);
		}

	}

	private String prepareChatMsg(String propName, String message) {
		ChatUser user = new ChatUser();
		user.setUserID(name);
		user.setRoomID(currentRoomID);
		user.setChatMsg(message);
		user.setIsActive(1);
		return XMLHelper.convertListObjectToXML(user, propName, ChatUser.class);
	}

	private String prepareDoChessTableMsg(String propName, String message) {
		return XMLHelper.convertListObjectToXML(new RoomTable(Integer.parseInt(currentRoomID)), propName,
				RoomTable.class);
	}

	@SuppressWarnings("unchecked")
	private void showChatPublic(String resultXML) {

		String processName = XMLHelper.getProcessName(resultXML);
		lstReturnUser = (ArrayList<ChatUser>) XMLHelper.convertXMLToListObject(
				resultXML, ChatUser.class);
		String publicRoomID = getPublicRoomID();
		if (publicRoomID.equals(currentRoomID)) {
			// Refresh listUser if not chat
			if (!processName.contains(Const.PROCESS_CHAT_PUBLIC_CHAT)) {
				listUser.removeAllItem();
				for (ChatUser user : lstReturnUser) {
					if (user.getIsDeleted() != Const.TRUE
							&& user.getRoomID().equals(currentRoomID)) {
						listUser.add(user.getUserID(),
								String.valueOf(user.getWin()),
								String.valueOf(user.getLoss()),
								String.valueOf(user.getRank_id()),
								String.valueOf(user.getGold()));
					}
				}
				refreshPanel(listUser.getColumnData());
			}

			for (ChatUser user : lstReturnUser) {
				if (user.getIsActive().equals(Const.TRUE)
						&& user.getRoomID().equals(currentRoomID)) {
					if (!processName.contains(Const.PROCESS_CHAT_PUBLIC_CHAT)) {
						textResult.append(user.getUserID() + " "
								+ user.getChatMsg() + "\n");
					} else {
						textResult.append(user.getUserID() + " : "
								+ user.getChatMsg() + "\n");
					}
				}
			}
		}
	}

	private void refreshPanel(String[][] columnData) {

		panel.remove(listUser);
		panel.revalidate();

		listUser = new MultiColumn(columnData, 5);
		panel.add(listUser);
		listUser.setBounds(286, 20, 270, 350);
		listUser.setFont(ver);
		listUser.setLayout(null);
		listUser.setSize(240, 350);
		listUser.refreshList();

		panel.revalidate();
	}

	@SuppressWarnings("unchecked")
	private void showDoChessTable(String resultXML) {		
		List<RoomTable> lstChessTable = (ArrayList<RoomTable>) XMLHelper
				.convertXMLToListObject(resultXML, RoomTable.class);
		boolean updateView = true;
		if(!lstChessTable.isEmpty()) {
			if(!currentRoomID.equals(String.valueOf(lstChessTable.get(0).getRoomId()))) {
				updateView = false;
			}
		}
		
		if(updateView) {
			// Clean all data if available
			DefaultTableModel modal = chessTable.getModel();
			modal.setRowCount(0);

			lstReturnChessTable.clear();

			for(RoomTable table : lstChessTable) {
				Object rowData[] = new Object[] {
						String.valueOf(table.getTableId()),
						table.getPlayer1Id(), table.getPlayer2Id(), table.getStatus() };
				System.out.println("status:" + rowData[3]);
				chessTable.getModel().addRow(rowData);
			}

			if (chessTable.getModel().getRowCount() == 0) {
				return;
			} else {
				chessTable.refreshTable();
			}
		}
	}

	@SuppressWarnings("unchecked")
	private void showResult(String resultXML) {

		try {
			String processName = XMLHelper.getProcessName(resultXML);

			if (processName.contains(Const.SERVICE_DO_CHESS_TABLE)) {
				showDoChessTable(resultXML);
			} else if (processName.contains(Const.SERVICE_CHAT_PUBLIC)) {
				showChatPublic(resultXML);
			} else if (processName.contains(Const.SERVICE_POPULAR_RELOGIN)) {
				// Show popular message
				lstReturnUser = (ArrayList<ChatUser>) XMLHelper
						.convertXMLToListObject(resultXML, ChatUser.class);
				if (lstReturnUser.get(0).getUserID().equals(name)) {
					JOptionPane.showMessageDialog(getComponent(0),
							Msg.MSG_ALREADY_LOGINED);
				}

			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private String getPublicRoomID() {
		// Display msg
		for (ChatUser user : lstReturnUser) {
			if (user.getIsActive().equals(1)) {
				return user.getRoomID();
			}
		}
		return "";

	}
}